/*
 * This file is part of the quickTools support library, dubbed "LucasCode"
 *
 * Copyright (C) 2005-2008 Lucas Romero
 *
 * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program; if not, see <http://www.gnu.org/licenses/>.
 */
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Text;
using System.Windows.Forms;
using ICSharpCode.SharpZipLib.Zip;
using System.Threading;

namespace LucasCode.UpdateInstaller
{
    public partial class FormInstaller : Form
    {
        private string[] args;
        private string m_ArchivePath = string.Empty;
        private string m_AppDir = string.Empty;
        public FormInstaller(string[] args)
        {
            this.args = args;
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            
        }

        private void AddLog(string text)
        {
            if (Log.Lines.Length > 0)
                Log.Text += Environment.NewLine;
            Log.Text += DateTime.Now.ToLongTimeString() + ": " + text;
        }

        private void StartUpdate()
        {
            UseWaitCursor = true;
            Thread.Sleep(2000);
            UseWaitCursor = false;
            while (Process.GetProcessesByName("quickReminder").Length > 0)
                MessageBox.Show("Please exit all quickReminder instances before updating!" + Environment.NewLine + "There are still " + Process.GetProcessesByName("quickReminder").Length + " processes running!");

            //AddLog("ver: 3");
            
            //MessageBox.Show("Update successful!");
           /* System.Diagnostics.Process.Start(
                m_AppDir + Path.DirectorySeparatorChar +
                "AutoUpdateInstaller.exe",
                "\"" + m_upd.DownloadedFile + "\" \"" + Path.GetDirectoryName(Application.ExecutablePath) + "\"");*/

            AddLog(lang.BackupStart);
            DirectoryInfo AppDir = new DirectoryInfo(m_AppDir);
            DirectoryInfo BackupDir =
                new DirectoryInfo(Path.GetDirectoryName(m_ArchivePath) + Path.DirectorySeparatorChar + "backup");
            if(!BackupDir.Exists)
                BackupDir.Create();
            if(!AppDir.Exists)
                AppDir.Create();
            ZipInputStream s = null;
            FileStream fs = null;
            try
            {
                FileStream zipstream = File.OpenRead(m_ArchivePath);
                s = new ZipInputStream(zipstream);
                progressBar1.Style = ProgressBarStyle.Continuous;
                progressBar1.Value = 0;
                progressBar1.Maximum = (int)zipstream.Length;
                ZipEntry theEntry;

                int file = 0;
                while ((theEntry = s.GetNextEntry()) != null)
                {
                    if(theEntry.IsDirectory/* || theEntry.Name == "AutoUpdateInstaller.exe"*/)
                        continue;
                    FileInfo fi =
                        new FileInfo(AppDir.FullName + Path.DirectorySeparatorChar +
                                     theEntry.Name.Replace("/", Path.DirectorySeparatorChar.ToString()));
                    if (fi.Exists)
                    {
                        DirectoryInfo d =
                            new DirectoryInfo(Path.GetDirectoryName(BackupDir.FullName + Path.DirectorySeparatorChar +
                                                                    theEntry.Name.Replace("/",
                                                                                          Path.DirectorySeparatorChar.
                                                                                              ToString())));
                        if(!d.Exists)
                            d.Create();
                        fi.CopyTo(BackupDir.FullName + Path.DirectorySeparatorChar +
                                  theEntry.Name.Replace("/", Path.DirectorySeparatorChar.ToString()), true);
                        AddLog(String.Format(lang.BackupFile, theEntry.Name.Replace("/", Path.DirectorySeparatorChar.ToString())));
                    }
                    if (!fi.Directory.Exists)
                        fi.Directory.Create();
                    fs = new FileStream(fi.FullName, FileMode.Create, FileAccess.Write);
                    int zipbytes;
					const int BLOCK_SIZE = 2048;
					Byte[] zipbuffer = new Byte[BLOCK_SIZE];
                    while((zipbytes = s.Read(zipbuffer,0,zipbuffer.Length)) > 0)
                    {
                        progressBar1.Value = (int)zipstream.Position;
                        //progressBar1.Value += (int)zipbytes;
                        fs.Write(zipbuffer,0,zipbytes);
                        Application.DoEvents();
                    }
                    //if (file >= 5)
                        //throw new Exception("blablabal");
                    fs.Close();
                    AddLog(String.Format(lang.UpdateFile,theEntry.Name.Replace("/", Path.DirectorySeparatorChar.ToString())));
                    file++;
                }
                MessageBox.Show(lang.UpdateSuccessful);
                System.Diagnostics.Process.Start(m_AppDir + Path.DirectorySeparatorChar +
                                                 "quickReminder.exe");
                Application.Exit();
            }
            catch(Exception ex)
            {
                AddLog("Error: " + ex.Message + "@" + ex.StackTrace);
                MessageBox.Show("Error: " + ex.Message + "@" + ex.StackTrace);
                MessageBox.Show(lang.UpdateUndo);
                copyDirectory(BackupDir.FullName,AppDir.FullName);
            }
            finally
            {
                if(s != null)
                    s.Close();
                if(fs != null)
                    fs.Close();
            }
        }
        public void copyDirectory(string Src,string Dst)
        {
            DirectoryInfo from = new DirectoryInfo(Src);
            DirectoryInfo to = new DirectoryInfo(Dst);
            AddLog(String.Format("CopyDirectory with args from '{0}' to '{1}'", Src, Dst));
            AddLog(String.Format("SubdirCount source: {0}", from.GetDirectories().Length));
            AddLog(String.Format("SubdirCount target: {0}", to.GetDirectories().Length));
            if (!to.Exists)
                to.Create();
            foreach (DirectoryInfo d in from.GetDirectories())
            {
                AddLog(String.Format("Copying folder {0} to {1}", d.FullName, to.FullName + Path.DirectorySeparatorChar + d.Name));
                copyDirectory(d.FullName, to.FullName + Path.DirectorySeparatorChar + d.Name);
            }
            foreach(FileInfo f in from.GetFiles())
            {
                string tosubpath = f.DirectoryName.Replace(from.FullName, "");
                if(tosubpath.StartsWith(Path.DirectorySeparatorChar.ToString()))
                    tosubpath = tosubpath.Substring(1,tosubpath.Length-1);
                AddLog("SubPath: '" + tosubpath + f.Name + "'");
                AddLog(String.Format("Copying file {0} to {1}", f.FullName, to.FullName + Path.DirectorySeparatorChar + tosubpath + f.Name));
                if (!Directory.Exists(to.FullName + Path.DirectorySeparatorChar + tosubpath))
                    Directory.CreateDirectory(to.FullName + Path.DirectorySeparatorChar + tosubpath);
                f.CopyTo(to.FullName + Path.DirectorySeparatorChar + tosubpath + f.Name, true);
            }
        }

        private void Form1_Shown(object sender, EventArgs e)
        {
            if (args.Length < 2)
            {
                MessageBox.Show("Too few arguments!");
                Application.Exit();
            }
            else
            {
                m_ArchivePath = args[0];
                m_AppDir = args[1];
                if (!File.Exists("ICSharpCode.SharpZipLib.dll"))
                {
                    MessageBox.Show("ZIP library not found, trying to get from application directory '" +
                                    m_AppDir + Path.DirectorySeparatorChar + "ICSharpCode.SharpZipLib.dll'");
                    File.Copy(m_AppDir + Path.DirectorySeparatorChar + "ICSharpCode.SharpZipLib.dll", "ICSharpCode.SharpZipLib.dll");
                }
                backgroundWorker1.RunWorkerAsync();
                //StartUpdate();
            }
        }

        private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            StartUpdate();
        }


        
    }
}